package com.turman.builibrary.refresh;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.Scroller;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class BRefreshLayout extends FrameLayout implements BRefresh {
    private BOverview.RefreshState state;
    private GestureDetector gestureDetector;
    private BRefresh.BRefreshListener refreshListener;
    protected BOverview overview;

    private AutoScroller autoScroller;

    private int lastY;
    //刷新时是否禁止滚动
    private boolean disableRefreshScroll;

    BGestureDetectorListener BGestureDetectorListener = new BGestureDetectorListener() {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float disX, float disY) {
            if (Math.abs(disX) > Math.abs(disY) || refreshListener != null && !refreshListener.enableRefresh()) {
                //横向滑动，或刷新被禁止则不处理
                return false;
            }

            //当前正在刷新时向上滑动则拦截事件并停止刷新
            if (state == BOverview.RefreshState.STATE_REFRESHING && Math.abs(disY) > Math.abs(disX) && e2.getY()<e1.getY()) {
                refreshFinished();
                return true;
            }

            if (disableRefreshScroll && state == BOverview.RefreshState.STATE_REFRESHING) {//刷新时是否禁止滑动
                return true;
            }

            View head = getChildAt(0);
            View child = BScrollUtil.findScrollableChild(BRefreshLayout.this);
            if (BScrollUtil.childScrolled(child)) {
                //如果列表发生了滚动则不处理
                return false;
            }
            //没有刷新或没有达到可以刷新的距离，且头部已经划出或下拉
            if ((state != BOverview.RefreshState.STATE_REFRESHING || head.getBottom() <= overview.mPullRefreshHeight) && (head.getBottom() > 0 || disY <= 0.0F)) {
                //还在滑动中
                if (state != BOverview.RefreshState.STATE_OVER_RELEASE) {
                    int speed;
                    //阻尼计算
                    if (child.getTop() < overview.mPullRefreshHeight) {
                        speed = (int) (lastY / overview.minDamp);
                    } else {
                        speed = (int) (lastY / overview.maxDamp);
                    }
                    //如果是正在刷新状态，则不允许在滑动的时候改变状态
                    boolean bool = moveDown(speed, true);
                    lastY = (int) (-disY);
                    return bool;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    };

    public BRefreshLayout(@NonNull Context context) {
        this(context, null);
    }

    public BRefreshLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BRefreshLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    public void setDisableRefreshScroll(boolean disable) {
        this.disableRefreshScroll = disable;
    }

    @Override
    public void refreshFinished() {
        View header = getChildAt(0);
        overview.onRefreshFinished();
        overview.setState(BOverview.RefreshState.STATE_INIT);
        int bottom = header.getBottom();
        if (bottom > 0) {
            recover(bottom);
        }
        state = BOverview.RefreshState.STATE_INIT;
    }

    @Override
    public void setRefreshListener(BRefreshListener listener) {
        this.refreshListener = listener;
    }

    @Override
    public void setRefreshOverview(BOverview overview) {
        if (overview != null) {
            removeView(overview);
        }
        this.overview = overview;
        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        addView(overview, 0, params);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //事件分发处理
        if (!autoScroller.isFinished()) {
            return false;
        }

        View header = getChildAt(0);
        if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_POINTER_INDEX_MASK) {
            //松开手
            if (header.getBottom() > 0) { //表示header有向下移动？
                if (state != BOverview.RefreshState.STATE_REFRESHING) {
                    recover(header.getBottom());
                    return false;
                }
            }
            lastY = 0;
        }
        boolean consumed = gestureDetector.onTouchEvent(ev); //手势器消费了该点击事件
        if ((consumed || (state != BOverview.RefreshState.STATE_INIT && state != BOverview.RefreshState.STATE_REFRESHING)) && header.getBottom() != 0) {
            ev.setAction(MotionEvent.ACTION_CANCEL);
            return super.dispatchTouchEvent(ev);
        }
        if (consumed) {
            return true;
        } else {
            return super.dispatchTouchEvent(ev);
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        View header = getChildAt(0);
        View child = getChildAt(1);
        if (header != null && child != null) {
            int childTop = child.getTop();
            if (state == BOverview.RefreshState.STATE_REFRESHING) {
                header.layout(0, overview.mPullRefreshHeight - header.getMeasuredHeight(), right, overview.mPullRefreshHeight);
                child.layout(0, overview.mPullRefreshHeight, right, overview.mPullRefreshHeight + child.getMeasuredHeight());
            } else {
                header.layout(0, childTop - header.getMeasuredHeight(), right, childTop);
                child.layout(0, childTop, right, childTop + child.getMeasuredHeight());
            }
            View other;
            for (int i = 2; i < getChildCount(); i++) {
                other = getChildAt(i);
                other.layout(0, top, right, bottom);
            }
        }
    }

    private void init() {
        gestureDetector = new GestureDetector(getContext(), BGestureDetectorListener);
        autoScroller = new AutoScroller();
    }

    private boolean moveDown(int offsetY, boolean nonAuto) {
        View header = getChildAt(0);
        View child = getChildAt(1);
        int childTop = child.getTop() + offsetY;

        if (childTop < 0) {
            offsetY = -child.getTop();
            //移动header和child到原始位置
            header.offsetTopAndBottom(offsetY);
            child.offsetTopAndBottom(offsetY);
            if (state != BOverview.RefreshState.STATE_REFRESHING) {
                state = BOverview.RefreshState.STATE_INIT;
            }
        } else if (state == BOverview.RefreshState.STATE_REFRESHING && childTop > overview.mPullRefreshHeight) {
            //如果正在下拉刷新中，禁止继续下拉
            return false;
        } else if (childTop <= overview.mPullRefreshHeight) {
            //还没有超出设定的刷新距离
            if (overview.getState() != BOverview.RefreshState.STATE_VISIBLE && nonAuto) {
                overview.onVisible();
                overview.setState(BOverview.RefreshState.STATE_VISIBLE);
                state = BOverview.RefreshState.STATE_VISIBLE;
            }
            header.offsetTopAndBottom(offsetY);
            child.offsetTopAndBottom(offsetY);
            if (childTop == overview.mPullRefreshHeight && state == BOverview.RefreshState.STATE_OVER_RELEASE) {
                refresh();
            }
        }else {
            if (overview.state != BOverview.RefreshState.STATE_OVER && nonAuto) {
                //超出设定的刷新距离
                overview.onOver();
                overview.setState(BOverview.RefreshState.STATE_OVER);
            }
            header.offsetTopAndBottom(offsetY);
            child.offsetTopAndBottom(offsetY);
        }
        if (overview != null) {
            overview.onScroll(header.getBottom(), overview.mPullRefreshHeight);
        }
        return true;
    }

    private void refresh() {
        if (refreshListener != null) {
            state = BOverview.RefreshState.STATE_REFRESHING;
            overview.onRefresh();
            overview.setState(BOverview.RefreshState.STATE_REFRESHING);
            refreshListener.onRefresh();
        }
    }

    private void recover(int dis) {
        if (refreshListener != null && dis > overview.mPullRefreshHeight) {
            //滚动到指定位置bottom-overview.mPullRefreshHeight
            autoScroller.recover(dis - overview.mPullRefreshHeight);
            state = BOverview.RefreshState.STATE_OVER_RELEASE;
        } else {
            autoScroller.recover(dis);
        }
    }

    private class AutoScroller implements Runnable {
        private Scroller scroller;
        private int lastY;
        private boolean isFinished;

        public AutoScroller() {
            scroller = new Scroller(getContext(), new LinearInterpolator());
            isFinished = true;
        }

        @Override
        public void run() {
            if (scroller.computeScrollOffset()) {//还未完成滚动
                moveDown(lastY - scroller.getCurrY(), false);
                lastY = scroller.getCurrY();
                post(this);
            } else {
                removeCallbacks(this);
                isFinished = true;
            }
        }

        void recover(int dis) {
            if (dis < 0) {
                return;
            }
            removeCallbacks(this);
            lastY = 0;
            isFinished = false;
            scroller.startScroll(0, 0, 0, dis, 300);
            post(this);
        }

        boolean isFinished() {
            return isFinished;
        }
    }
}

















